/*
 * Copyright (c) 2012 Travis Geiselbrecht
 *
 * Use of this source code is governed by a MIT-style
 * license that can be found in the LICENSE file or at
 * https://opensource.org/licenses/MIT
 */
#include <lk/debug.h>
#include <assert.h>
#include <dev/gpio.h>
#include <platform/hc32.h>
#include <platform/gpio.h>
#include <hc32_ddl.h>
#include <hc32f46x.h>

static en_port_t port_to_pointer(unsigned int port) {
    switch (port) {
        default:
        case GPIO_PORT_A:
            return PortA;
        case GPIO_PORT_B:
            return PortB;
        case GPIO_PORT_C:
            return PortC;
        case GPIO_PORT_D:
            return PortD;
        case GPIO_PORT_E:
            return PortE;
        case GPIO_PORT_H:
            return PortH;
    }
}

static void enable_port(unsigned int port) {

}

void hc32_gpio_early_init(void) {
	PORT_DebugPortSetting(TRST, Disable); //PB4
}

int gpio_config(unsigned nr, unsigned flags) {

    uint port = GPIO_PORT(nr);
    uint pin = GPIO_PIN(nr);

    enable_port(port);

    stc_port_init_t init;	
	MEM_ZERO_STRUCT(init);

    init.enExInt = Enable;

    if (flags & GPIO_INPUT) {
        init.enPinMode = Pin_Mode_In;
    } else if  (flags & GPIO_OUTPUT) {
        init.enPinMode = Pin_Mode_Out;
    } else if  (flags & GPIO_HC32_AF) {
		PORT_SetFunc(port_to_pointer(port), 1 << pin, GPIO_AFNUM(flags), Disable);
		return 0;
    } else{
		init.enPinMode = Pin_Mode_Ana;
	}

    if (flags & GPIO_PULLUP) {
        init.enPullUp = Enable;
    } else if (flags & GPIO_PULLDOWN) {
        init.enPullUp = Disable;
    }

    if (flags & GPIO_HC32_OD) {
        init.enPinOType = Pin_OType_Od;
    } else {
        init.enPinOType = Pin_OType_Cmos;
    }

	PORT_Init(port_to_pointer(port), 1 << pin, &init);

    return 0;
}

void gpio_set(unsigned nr, unsigned on) {
	if(on)
		PORT_SetBits(port_to_pointer(GPIO_PORT(nr)), 1 << GPIO_PIN(nr));
	else
		PORT_ResetBits(port_to_pointer(GPIO_PORT(nr)), 1 << GPIO_PIN(nr));
}

int gpio_get(unsigned nr) {
    return PORT_GetBit(port_to_pointer(GPIO_PORT(nr)), 1 << GPIO_PIN(nr));
}

